import time
from common import (
    lib60870,
    CS104_Slave, TLSConfiguration, IMasterConnection, CS101_ASDU, CP56Time2a, CS101_CauseOfTransmission,
    CS104_PeerConnectionEvent, CS101_ASDUHandler,
    CS101_InterrogationHandler, CS101_ClockSynchronizationHandler,
    CS104_ConnectionRequestHandler, CS104_ConnectionEventHandler
)
from ctypes import c_void_p, c_int, c_uint8, c_bool, c_char_p, POINTER, Structure

# 从站特有函数封装（iec60870_slave.h）
lib60870.IMasterConnection_sendASDU.restype = c_bool
lib60870.IMasterConnection_sendASDU.argtypes = [IMasterConnection, CS101_ASDU]

lib60870.IMasterConnection_sendACT_CON.restype = c_bool
lib60870.IMasterConnection_sendACT_CON.argtypes = [IMasterConnection, CS101_ASDU, c_bool]

# 从站特有函数封装（cs104_slave.h）
lib60870.CS104_Slave_create.restype = CS104_Slave
lib60870.CS104_Slave_create.argtypes = [c_int, c_int]

# lib60870.CS104_Slave_createSecure.restype = CS104_Slave
# lib60870.CS104_Slave_createSecure.argtypes = [c_int, c_int, TLSConfiguration]

lib60870.CS104_Slave_setLocalAddress.restype = None
lib60870.CS104_Slave_setLocalAddress.argtypes = [CS104_Slave, c_char_p]

lib60870.CS104_Slave_setLocalPort.restype = None
lib60870.CS104_Slave_setLocalPort.argtypes = [CS104_Slave, c_int]

lib60870.CS104_Slave_start.restype = None
lib60870.CS104_Slave_start.argtypes = [CS104_Slave]

lib60870.CS104_Slave_stop.restype = None
lib60870.CS104_Slave_stop.argtypes = [CS104_Slave]

lib60870.CS104_Slave_setInterrogationHandler.restype = None
lib60870.CS104_Slave_setInterrogationHandler.argtypes = [CS104_Slave, CS101_InterrogationHandler, c_void_p]

lib60870.CS104_Slave_setASDUHandler.restype = None
lib60870.CS104_Slave_setASDUHandler.argtypes = [CS104_Slave, CS101_ASDUHandler, c_void_p]

lib60870.CS104_Slave_setClockSyncHandler.restype = None
lib60870.CS104_Slave_setClockSyncHandler.argtypes = [CS104_Slave, CS101_ClockSynchronizationHandler, c_void_p]

lib60870.CS104_Slave_setConnectionRequestHandler.restype = None
lib60870.CS104_Slave_setConnectionRequestHandler.argtypes = [CS104_Slave, CS104_ConnectionRequestHandler, c_void_p]

lib60870.CS104_Slave_setConnectionEventHandler.restype = None
lib60870.CS104_Slave_setConnectionEventHandler.argtypes = [CS104_Slave, CS104_ConnectionEventHandler, c_void_p]

# 从站高级封装类
class CS104Slave:
    def __init__(self, max_low_prio_queue_size, max_high_prio_queue_size, tls_config=None):
        if tls_config:
            self.slave = lib60870.CS104_Slave_createSecure(
                max_low_prio_queue_size, max_high_prio_queue_size, tls_config)
        else:
            self.slave = lib60870.CS104_Slave_create(
                max_low_prio_queue_size, max_high_prio_queue_size)
        
        self.interrogation_handler = None
        self.clock_sync_handler = None
        self.connection_request_handler = None
        self.connection_event_handler = None

    def set_local_address(self, ip_address):
        lib60870.CS104_Slave_setLocalAddress(self.slave, ip_address.encode('utf-8'))

    def set_local_port(self, port):
        lib60870.CS104_Slave_setLocalPort(self.slave, port)

    def start(self):
        lib60870.CS104_Slave_start(self.slave)

    def stop(self):
        lib60870.CS104_Slave_stop(self.slave)

    def set_interrogation_handler(self, handler):
        self.interrogation_handler = CS101_InterrogationHandler(handler)
        lib60870.CS104_Slave_setInterrogationHandler(
            self.slave, self.interrogation_handler, None)
        
    def set_asdu_handler(self, handler):
        self.audu_handler = CS101_ASDUHandler(handler)
        lib60870.CS104_Slave_setASDUHandler(
            self.slave, self.audu_handler, None)

    def set_clock_sync_handler(self, handler):
        self.clock_sync_handler = CS101_ClockSynchronizationHandler(handler)
        lib60870.CS104_Slave_setClockSyncHandler(
            self.slave, self.clock_sync_handler, None)

    def set_connection_request_handler(self, handler):
        self.connection_request_handler = CS104_ConnectionRequestHandler(handler)
        lib60870.CS104_Slave_setConnectionRequestHandler(
            self.slave, self.connection_request_handler, None)

    def set_connection_event_handler(self, handler):
        self.connection_event_handler = CS104_ConnectionEventHandler(handler)
        lib60870.CS104_Slave_setConnectionEventHandler(
            self.slave, self.connection_event_handler, None)


# 使用示例
def example_usage():
    # 创建从站实例
    slave = CS104Slave(100, 100)
    
    # 设置本地地址和端口
    slave.set_local_address("0.0.0.0")
    slave.set_local_port(2404)
    
    # 定义回调函数
    def interrogation_handler(parameter, connection, asdu, qoi):
        print(f"Received interrogation request, QOI: {qoi}")
       # 只处理站级 interrogation (QOI=20)
        if qoi == 20:
            # 获取应用层参数
            al_params = lib60870.IMasterConnection_getApplicationLayerParameters(connection)
            
            # 发送ACT_CON确认
            lib60870.IMasterConnection_sendACT_CON(connection, asdu, False)
            
            # 1. 返回遥测数据 (MeasuredValueScaled - 模拟量)
            telemetry_asdu = lib60870.CS101_ASDU_create(
                al_params, 
                False,  # 无时间戳
                CS101_CauseOfTransmission.INTERROGATED_BY_STATION.value,  # COT
                0,      # 公共地址
                1,      # 信息对象地址
                False,  # 非序列
                False   # 非测试模式
            )
            
            # 添加遥测信息对象 (IOA:100, 101, 102)
            io1 = lib60870.MeasuredValueScaled_create(None, 100, -1, 0)  # 质量0=GOOD
            lib60870.CS101_ASDU_addInformationObject(telemetry_asdu, io1)
            
            io2 = lib60870.MeasuredValueScaled_create(io1, 101, 23, 0)
            lib60870.CS101_ASDU_addInformationObject(telemetry_asdu, io2)
            
            io3 = lib60870.MeasuredValueScaled_create(io2, 102, 2300, 0)
            lib60870.CS101_ASDU_addInformationObject(telemetry_asdu, io3)
            
            # 销毁信息对象(已添加到ASDU，无需保留)
            lib60870.InformationObject_destroy(io1)
            
            # 发送遥测ASDU
            lib60870.IMasterConnection_sendASDU(connection, telemetry_asdu)
            lib60870.CS101_ASDU_destroy(telemetry_asdu)
            
            # 2. 返回遥信数据 (SinglePointInformation - 开关量)
            telecommand_asdu = lib60870.CS101_ASDU_create(
                al_params,
                False,
                CS101_CauseOfTransmission.INTERROGATED_BY_STATION.value,
                0,
                1,
                False,
                False
            )
            
            # 添加遥信信息对象 (IOA:104, 105)
            io4 = lib60870.SinglePointInformation_create(None, 104, True, 0)  # 状态True=合
            lib60870.CS101_ASDU_addInformationObject(telecommand_asdu, io4)
            
            io5 = lib60870.SinglePointInformation_create(io4, 105, False, 0)  # 状态False=分
            lib60870.CS101_ASDU_addInformationObject(telecommand_asdu, io5)
            
            # 销毁信息对象
            lib60870.InformationObject_destroy(io4)
            
            # 发送遥信ASDU
            lib60870.IMasterConnection_sendASDU(connection, telecommand_asdu)
            lib60870.CS101_ASDU_destroy(telecommand_asdu)
            
            # 发送结束确认
            lib60870.IMasterConnection_sendACT_TERM(connection, asdu)
        else:
            # 其他组返回否定确认
            lib60870.IMasterConnection_sendACT_CON(connection, asdu, True)
        
        return True
    
    def clock_sync_handler(parameter, connection, asdu, new_time):
        print("Received clock synchronization request")
        asdu_hex = f"0x{asdu:X}" if asdu is not None else "None"
        print(f"收到ASDU: {asdu_hex} {asdu}")
        return True

    def  asdu_handler(parameter, connection, asdu):
        print("Received ASDU")
        asdu_hex = f"0x{asdu:X}" if asdu is not None else "None"
        print(f"收到ASDU: {asdu_hex} {asdu}")
        return True
    
    def connection_request_handler(parameter, ip_address):
        print(f"Connection request from {ip_address.decode('utf-8')}")
        return True  # 接受连接
    
    def connection_event_handler(parameter, connection, event):
        event_str = CS104_PeerConnectionEvent(event).name
        print(f"Connection event: {event_str}")
    
    # 设置回调函数
    slave.set_interrogation_handler(interrogation_handler)
    slave.set_clock_sync_handler(clock_sync_handler)
    slave.set_connection_request_handler(connection_request_handler)
    slave.set_connection_event_handler(connection_event_handler)
    slave.set_asdu_handler(asdu_handler)
    
    # 启动从站
    slave.start()
    print("CS10asdf4 slave started. Press Ctrl+C to stop.")
    
    # 运行一段时间
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        pass
    
    # 停止从站
    slave.stop()
    print("CS104 slave stopped")

if __name__ == "__main__":
    example_usage()